package com.fuego.creditsystemnews.service.impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuego.creditsystemnews.mapper.NewsMapper;
import com.fuego.creditsystemnews.service.IFollowService;
import com.fuego.creditsystemnews.service.INewsService;
import com.fuego.creditsystemuser.service.IUserService;
import jakarta.annotation.Resource;
import org.example.dto.Result;
import org.example.dto.ScrollResult;
import org.example.entity.Follow;
import org.example.entity.News;
import org.example.entity.User;
import org.example.utils.SystemConstants;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static org.example.utils.RedisConstants.FEED_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class NewsServiceImpl extends ServiceImpl<NewsMapper, News> implements INewsService {
    @Resource
    private IUserService userService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private IFollowService followService;
    public Result queryHotNews(@RequestParam(value = "current", defaultValue = "1") Integer current, @RequestParam("userId") Long userId) {
        // 根据用户查询
        Page<News> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<News> records = page.getRecords();
        List<News> result = new ArrayList<>();
        for(int i=current;i<current+SystemConstants.MAX_PAGE_SIZE;i++)
        {
            result.add(records.get(i));
        }

        // 查询用户
        result.forEach(news -> {
            this.isNewsLiked(news,userId);
            this.queryNewsUser(news);
        });
        return Result.ok(result);
    }

    @Override
    public Result queryNewsById(Long id,Long userId) {
        //1查询news
        News news =getById(id);
        if(news==null)
        {
            return Result.fail("笔记不存在");
        }
        // 2查询news有关的用户
        queryNewsUser(news);
        //3.查询news是否被点赞
        isNewsLiked(news,userId);
        return Result.ok(news);
    }

    private void isNewsLiked(News news,Long userId) {

        // 2判断当前登录用户是否已经点赞
        String key="news:liked:" +news.getId();
        Double score =stringRedisTemplate.opsForZSet().score(key,userId.toString());
        news.setIsLike(score!=null);
    }

    @Override
    public Result likeNews(Long id,Long userId) {

        // 2判断当前登录用户是否已经点赞
        String key="news:liked:" +id;
        Double score =stringRedisTemplate.opsForZSet().score(key,userId.toString());
        if(score==null)
        {   // 3如果未点赞，可以点赞
            // 3.1数据库点赞数+1
            boolean isSuccess = update().setSql("liked=liked+1").eq("id", id).update();
            // 3.2保存用户到redis的sortedset集合 zadd key value score
            if(isSuccess){
                stringRedisTemplate.opsForZSet().add(key,userId.toString(),System.currentTimeMillis());
            }
        }else {
            //4如果已点赞，取消点赞

            //4.1数据库点赞数-1
            boolean isSuccess = update().setSql("liked=liked-1").eq("id", id).update();
            // 4.2把用户从redis的set集合移除
            stringRedisTemplate.opsForZSet().remove(key, userId.toString());
        }

        return Result.ok();

    }


    @Override
    public Result queryNewsOfFollow(Long max, Integer offset,Long userId) {

        //2查询收件箱
        String key=FEED_KEY+userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(key, 0, max, offset, 2);
//        非空判断
        if(typedTuples==null || typedTuples.isEmpty()){
            return Result.ok();
        }
//        3解析数据：newsId、minTime时间戳、offset
        List<Long> ids=new ArrayList<>((typedTuples.size()));
        long minTime=0;
        int os=1;
        for(ZSetOperations.TypedTuple<String> tuple:typedTuples){
//            获取id
            String idStr=tuple.getValue();
            ids.add(Long.valueOf(tuple.getValue()));
//            获取分数
            Long time=tuple.getScore().longValue();
            if(time==minTime){
                os++;
            }
            else {
                minTime=time;
                os=1;
            }

        }
//        4根据id查询news
        String idStr=StrUtil.join(",",ids);
        List<News> newss = query().in("id",ids).last("ORDER BY FIELD(id," + idStr + ")").list();

        for (News news : newss) {
            // 2查询news有关的用户
            queryNewsUser(news);
            //3.查询news是否被点赞
            isNewsLiked(news,userId);
        }


        //        封装并返回
        ScrollResult r=new ScrollResult();
        r.setList(newss);
        r.setOffset(os);
        r.setMinTime(minTime);
        return Result.ok(r);
    }

    private void queryNewsUser(News news) {
        if (news == null || news.getUserId() == null) {
            log.warn("News or userId is null: {}"+news);
            news.setName("Unknown");
            news.setIcon("");
            return;
        }
        User user = userService.getById(news.getUserId());
        if (user == null) {
            log.warn("User not found for userId: {}"+news.getUserId());
            news.setName("Unknown");
            news.setIcon("");
            return;
        }
        news.setName(user.getNickName());
        news.setIcon(user.getIcon());
    }
//    private void queryNewsUser(News news) {
//        Long userId = news.getUserId();
//        User user = userService.getById(userId);
//        news.setName(user.getNickName());
//        news.setIcon(user.getIcon());
//    }


    @Override
    public Result queryNewsByUserId(@RequestParam(value = "current", defaultValue = "1") Integer current, @RequestParam("userId") Long userId) {
            // 根据用户查询
            Page<News> page = query()
                    .orderByDesc("liked")
                    .eq("user_id", userId)
                    .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
            // 获取当前页数据
            List<News> records = page.getRecords();
            // 查询用户
            records.forEach(news -> {
                this.isNewsLiked(news,userId);
                this.queryNewsUser(news);
            });
            return Result.ok(records);

    }
}
